package com.guanzi.big_data_mq_process.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guanzi.big_data_mq_process.dao.UsersDao;
import com.guanzi.big_data_mq_process.model.bo.UserOrderBO;
import com.guanzi.big_data_mq_process.model.entity.Users;
import com.guanzi.big_data_mq_process.model.query.UsersQuery;
import com.guanzi.big_data_mq_process.model.vo.UsersVO;
import com.guanzi.big_data_mq_process.service.IUsersService;
import com.guanzi.big_data_mq_process.util.PageResult;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * (Users) 服务实现类
 *
 * @author xuguang
 * @since 2025-05-06 21:57:45
 */
@Slf4j
@Service
public class UsersServiceImpl extends ServiceImpl<UsersDao, Users> implements IUsersService {

    @Autowired
    @Qualifier("exportThreadPool")
    private ThreadPoolExecutor exportThreadPool;

    /**
     * 分页列表
     */
    @Override
    public PageResult<UsersVO> getPage(UsersQuery query) {
        Page<Users> page = new Page<>(query.getPageNum(), query.getPageSize());
        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();

        // 排序
        //SortDTO sortDto = query.getSortDto();
        // if (null != sortDto) {
        //     if (sortDto.getColumnName().equals("xxxTime")) {
        //         sortDto.setColumnName(ColumnUtils.toUnderscoreCase(sortDto.getColumnName()));
        //     }
        // }

        return new PageResult(this.baseMapper.getPage(page, queryWrapper, query));
    }


    /**
     * 详情
     */
    @Override
    public UsersVO getInfo(String id) {
        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("user_id", id);
        return this.baseMapper.getInfo(queryWrapper);
    }

    /**
     * 删除数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByIdList(List<String> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new RuntimeException("待删除的数据不能为空!");
        }
        UpdateWrapper<Users> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                // TODO 如果有逻辑删除字段,以及主键ID
                .set("delete_mark", 1)
                .in("user_id", idList);
        return update(updateWrapper);
    }

    @Override
    public void updateUserActiveTime(Integer userId) {
        new UpdateChainWrapper<>(this.baseMapper)
                .set("created_at", new Timestamp(System.currentTimeMillis()))
                .eq("user_id", userId)
                .update();
    }

    @Override
    public void exportData(HttpServletResponse response) throws Exception {
        response.addHeader("Content-Type", MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.addHeader("Content-Disposition", "attachment;filename=test.xlsx");

        int total = 1000;
        int pageSize = 250;
//        int pageSize = 500000;
        // 分多少页
        int pageTotal = (total % pageSize == 0 ? total / pageSize : total / pageSize + 1);

        CountDownLatch countDownLatch = new CountDownLatch(pageTotal);
        long start = System.currentTimeMillis();

//        List<UserOrderBO> userOrderDataList = this.baseMapper.getExportDataList();

        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), UserOrderBO.class)
                .autoCloseStream(false)
                .build();

        for (int i = 0; i < pageTotal; i++) {
            int startIndex = i * pageSize;
            String sheetName = "用户订单记录" + i;
            int sheetIndex = i;

            exportThreadPool.submit(() -> {
                try {
                    long threadStart = System.currentTimeMillis();
                    List<UserOrderBO> exportDataList = this.baseMapper.getExportDataList(startIndex);
                    long threadQueryEnd = System.currentTimeMillis();
                    log.info("线程: {} 查询完成，查询耗时：{} ms", Thread.currentThread().getName(), (threadQueryEnd - threadStart));

                    WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex, sheetName).build();

                    synchronized (excelWriter) {
                        excelWriter.write(exportDataList, writeSheet);
                    }
                    log.info("线程: {} 写入完成，写入耗时：{} ms", Thread.currentThread().getName(), (System.currentTimeMillis() - threadQueryEnd));

                } catch (Exception e) {
                    e.printStackTrace();
                    response.reset();
                    try {
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "导出失败!");
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                } finally {
                    countDownLatch.countDown();
                }
            });
        }

        // 等待所有线程完成
        countDownLatch.await();
        // 完成写入
        excelWriter.finish();

        long end = System.currentTimeMillis();
        log.info("共耗时：{} ms", (end - start));
    }

}
